package com.lechi.web.runner;

import cn.hutool.json.JSONUtil;
import com.lechi.iot.netty.utils.NettyCacheUtils;
import com.lechi.web.constants.Constants;
import com.lechi.web.dto.IotDeviceCmdParseDto;
import com.lechi.web.framework.util.GuavaCacheUtil;
import com.lechi.web.service.IIotDeviceCmdService;
import com.lechi.web.service.IIotWeatherDictService;
import com.lechi.web.system.domain.IotDeviceCmdParse;
import com.lechi.web.system.domain.IotDeviceCmdSchedule;
import com.lechi.web.system.domain.IotWeatherDeviceBo;
import com.lechi.web.system.domain.IotWeatherSensorParseBo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/**
 * 项目启动后缓存传感器指令解析格式
 */
@Slf4j
@Component("CacheCmdParseMsg")
@Order(4)
public class CacheCmdParseMsg implements CommandLineRunner {

    @Autowired
    private IIotDeviceCmdService iotDeviceCmdService;

    @Autowired
    private IIotWeatherDictService iotWeatherDictService;

    public void run(String... args) {
        Long deviceId = args.length != 0 ? Long.parseLong(args[0]) : null;
        String gateWayType = args.length >= 1 ? args[1] : null;
        if (Constants.WEATHER2017.equals(gateWayType)) {
            cacheTcpWeather(deviceId);
        } else {
            cacheTcpWeather(deviceId);
            cacheModbusTcp(deviceId);
        }
    }

    private void cacheModbusTcp(Long deviceId) {
        List<IotDeviceCmdSchedule> iotDeviceList = iotDeviceCmdService.selectIotDeviceCmdListForSchedule(deviceId);
        List<IotDeviceCmdParse> iotDeviceCmdCreateList = iotDeviceCmdService.selectIotDeviceCmdListByOrder(deviceId);
        for (IotDeviceCmdSchedule iotDeviceCmdSchedule : iotDeviceList) {
            List<IotDeviceCmdParseDto> retList = new ArrayList<>();
            String deviceSNAndAddr = iotDeviceCmdSchedule.getDeviceSn() + "_" + iotDeviceCmdSchedule.getStationAddr();
            int benginBit = 1;
            for (IotDeviceCmdParse iotDeviceCmdCreate : iotDeviceCmdCreateList) {
                String deviceSNAndAddrKey = iotDeviceCmdCreate.getDeviceSn() + "_" + iotDeviceCmdCreate.getStationAddr();
                if (deviceSNAndAddr.equals(deviceSNAndAddrKey)) {
                    IotDeviceCmdParseDto iotDeviceCmdParseDto = new IotDeviceCmdParseDto();
                    BeanUtils.copyProperties(iotDeviceCmdCreate, iotDeviceCmdParseDto);
                    if (Constants.FLOAT_FORMAT_32.equals(iotDeviceCmdCreate.getDataFormat()) || Constants.INTEGER_DATA_FORMAT_32.equals(iotDeviceCmdCreate.getDataFormat())) {
                        iotDeviceCmdParseDto.setBeginIndex((benginBit - 1) * 4);
                        iotDeviceCmdParseDto.setEndIndex(iotDeviceCmdParseDto.getBeginIndex() + 4);
                        benginBit++;
                    }
                    if (Constants.FLOAT_FORMAT_16.equals(iotDeviceCmdCreate.getDataFormat()) || Constants.INTEGER_DATA_FORMAT_16.equals(iotDeviceCmdCreate.getDataFormat())) {
                        iotDeviceCmdParseDto.setBeginIndex((benginBit - 1) * 2);
                        iotDeviceCmdParseDto.setEndIndex(iotDeviceCmdParseDto.getBeginIndex() + 2);
                        benginBit++;
                    }
                    retList.add(iotDeviceCmdParseDto);
                }
            }
            NettyCacheUtils.put(deviceSNAndAddr, retList);
        }
    }

    private void cacheTcpWeather(Long deviceId) {
        final List<IotWeatherDeviceBo> weatherDeviceList = iotWeatherDictService.selectIotWeatherDeviceList(deviceId).stream()
                .map(iotWeatherDeviceBo -> {
                    IotWeatherDeviceBo weatherDeviceDto = JSONUtil.toBean(iotWeatherDeviceBo.getContent(), IotWeatherDeviceBo.class);
                    weatherDeviceDto.setDeviceId(iotWeatherDeviceBo.getDeviceId());
                    weatherDeviceDto.setDeviceStation(iotWeatherDeviceBo.getDeviceStation());
                    weatherDeviceDto.setInstrumentId(iotWeatherDeviceBo.getInstrumentId());

//                    weatherDeviceDto.setWatchDataIndex(iotWeatherDeviceBo.getWatchDataIndex());
//                    weatherDeviceDto.setQualityIndex(iotWeatherDeviceBo.getQualityIndex());
//                    weatherDeviceDto.setStateNumIndex(iotWeatherDeviceBo.getStateNumIndex());
//                    weatherDeviceDto.setSensorNumIndex(iotWeatherDeviceBo.getSensorNumIndex());
                    return weatherDeviceDto;
                }).toList();
        GuavaCacheUtil.getCmdParseTableMap().put(Constants.WEATHER2017, weatherDeviceList);

        final List<IotWeatherSensorParseBo> weatherSensorsList = iotWeatherDictService.selectIotWeatherSensorList(deviceId);
        for (IotWeatherDeviceBo deviceDto : weatherDeviceList) {
            String deviceFlag = String.join("_", String.valueOf(deviceDto.getDeviceId()), deviceDto.getInstrumentId(), deviceDto.getDeviceStation());
            List<IotWeatherSensorParseBo> sensorParseBoList = new ArrayList<>();
            for (IotWeatherSensorParseBo sensorBo : weatherSensorsList) {
                String sensorFlag = String.join("_", String.valueOf(sensorBo.getDeviceId()), sensorBo.getInstrumentId(), sensorBo.getDeviceStation());
                if (Objects.equals(sensorFlag, deviceFlag)) {
                    sensorParseBoList.add(sensorBo);
                }
            }
            GuavaCacheUtil.getCmdParseTableMap().put(deviceFlag, sensorParseBoList);
        }
    }
}


